#include "treemodel.h"
#include <QStringList>
#include <QDebug>
#include <QFileInfo>
#include <QDir>
#include <QStandardPaths>
#include <QCoreApplication>

TreeModel::TreeModel(QObject *parent)
    : QAbstractItemModel(parent)
{
    m_emptyItem = new CusTreeNode();
    m_emptyItem->parent = nullptr;
    loadData();
}

TreeModel::~TreeModel()
{
    freeModelData();
}

LPCusTreeNode TreeModel::createNodeByFile(const QString& fileName, const QString& TestData)
{
    LPCusTreeNode pNode = new CusTreeNode();
    pNode->qsNodeName = fileName;
    pNode->qsNodeTestData = TestData;
    m_listNodes.push_back(pNode);
    return pNode;
}

void TreeModel::loadData()
{
    m_rootItem = createNodeByFile("root", "root");
    m_emptyItem->insertNode(m_rootItem);
    auto node2 = createNodeByFile(QStringLiteral("文件2"), "2222");
    m_rootItem->insertNode(node2);
    auto node3 = createNodeByFile(QStringLiteral("文件3"), "3333");
    node2->insertNode(node3);
    auto node4 = createNodeByFile(QStringLiteral("文件4"), "4444");
    node2->insertNode(node4);
    auto node5 = createNodeByFile(QStringLiteral("文件5"), "5555");
    m_rootItem->insertNode(node5);
    // 节点5下面放入10万个节点试试
    for(int idx = 0; idx < 100000; ++idx) {
        auto node = createNodeByFile(QStringLiteral("文件%1").arg(idx), "节点5的子文件");
        node5->insertNode(node);
    }

    resetModelData(m_rootItem);
    emit layoutChanged();
}

QHash<int, QByteArray> TreeModel::roleNames() const
{
    QHash<int, QByteArray> names(QAbstractItemModel::roleNames());
    names[NODE_NAME] = "name";
    names[NODE_PTR] = "dataptr";
    return names;
}

QVariant TreeModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    LPCusTreeNode item = static_cast<LPCusTreeNode>(index.internalPointer());
    if(item == nullptr)
        return QVariant();

    switch(role) {
    case NODE_NAME:
        return item->qsNodeName;
    case NODE_PTR:
        return (long long)(item);
    }

    return QVariant();
}

bool TreeModel::setData(const QModelIndex &index, const QVariant &value, \
                    int role)
{
    if (!index.isValid())
        return false;

    LPCusTreeNode item = static_cast<LPCusTreeNode>(index.internalPointer());
    switch(role) {
        case NODE_NAME:
        {
            if(item->qsNodeName == value.toString())
                break;
            QString newName = value.toString();
            item->qsNodeName = newName;
            emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole, NODE_NAME});
            break;
        }
    }

    updateModelData();
    return true;
}

Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::NoItemFlags;

    return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}

QVariant TreeModel::headerData(int section, Qt::Orientation orientation,
                               int role) const
{
    return QVariant();
}

void TreeModel::declareQML()
{
    qmlRegisterType<TreeModel>("TreeModel", 1, 0, "TreeModel");
}

void TreeModel::freeModelData()
{
    for(auto& node : m_listNodes)
    {
        delete node;
        node = nullptr;
    }
}

int TreeModel::columnCount(const QModelIndex &parent) const
{
    return 1;
}

QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!hasIndex(row, column, parent))
        return QModelIndex();

    LPCusTreeNode parentItem;

    if (!parent.isValid())
        parentItem = m_emptyItem;
    else
        parentItem = static_cast<LPCusTreeNode>(parent.internalPointer());

    if(parentItem != nullptr &&  row >= 0 && parentItem->lstChildNodes.size() > row)
    {
        LPCusTreeNode childItem = parentItem->lstChildNodes.value(row);
        QModelIndex create = createIndex(row, column, childItem);
        return create;
    }

    return QModelIndex();
}

QModelIndex TreeModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

    LPCusTreeNode childItem = static_cast<LPCusTreeNode>(index.internalPointer());
    if(childItem == nullptr)
        return QModelIndex();

    LPCusTreeNode parentItem = childItem->parent;
    if (parentItem == m_emptyItem || parentItem == nullptr)
        return QModelIndex();

    if(parentItem->parent == nullptr)
    {
        return QModelIndex();
    }
    else
    {
        for(auto rowIndex = 0; rowIndex < parentItem->parent->lstChildNodes.size(); rowIndex++)
        {
                if(parentItem->parent->lstChildNodes.at(rowIndex) == parentItem)
                    return createIndex(rowIndex, index.column(), parentItem);
        }
    }
    return QModelIndex();
}

int TreeModel::rowCount(const QModelIndex &parent) const
{
    LPCusTreeNode parentItem;
    if (!parent.isValid())
        parentItem = m_emptyItem;
    else
        parentItem = static_cast<LPCusTreeNode>(parent.internalPointer());

    return parentItem ? parentItem->lstChildNodes.count() : 0;
}

void TreeModel::resetModelData(LPCusTreeNode rootItem)
{
    if(m_emptyItem)
    {
        delete m_emptyItem;
        m_emptyItem = nullptr;
    }
    if(m_emptyItem == nullptr)
    {
        m_emptyItem = new CusTreeNode();
    }
    m_emptyItem->parent = nullptr;
    if(rootItem != nullptr)
    {
        m_emptyItem->insertNode(rootItem);
        rootItem->parent = m_emptyItem;
    }
}

void TreeModel::beginResetTreeModel()
{
    beginResetModel();
}

void TreeModel::endResetTreeModel()
{
    endResetModel();
}

void TreeModel::updateModelData()
{
    emit layoutChanged();
}


void TreeModel::startDeletelModelData(const QModelIndex &parent, int first, int last)
{
    beginRemoveRows(parent, first, last);
}

void TreeModel::endDeleteModelData()
{
    endRemoveRows();
}

void TreeModel::startInsertModelData(const QModelIndex &parent, int first, int last)
{
    beginInsertRows(parent, first, last);
}

void TreeModel::endInsertModelData()
{
    endInsertRows();
}


